package com.wdl.fm.core.shiro;

import com.wdl.fm.common.constants.GlobalConstant;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.AccessControlFilter;
import org.apache.shiro.web.util.WebUtils;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpSession;

/**
 * Created by Administrator on 2017/6/15.
 */
/*描述
        在使用shiro的时候,经常会有一种需求: 把登录成功后的用户对象存放到session中,方面其他地方调用。存放到session这个步骤到底应该在哪里去做,有几个地方比较合适:

        调用 Subject.login() 的时候
        使用 cas 进行单点认证的时候,集成 CasFilter 重写 onLoginSuccess() 方法
        实现 AuthenticationListener 接口,实现 onSuccess 接口
        以上三种方法,都可以做到登录成功以后把用户对象存放到session中,但是都没有考虑到一点,使用 保存登录(Remembere) 进行自动登录的情况,以上的几个方法都不会被调用,也没有找到 onRemembereLogin 类似的接口。

        解决方案
        在需要用户登录权限的地方添加一个过滤器: 判断如果用户是登录状态,并且session里的用户对象为空,则去数据库中查询用户对象放入session中。*/

public class UserSessionFilter extends AccessControlFilter {
    @Override
    protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception {
        Subject subject = getSubject(request, response);
        if (subject == null) {
            // 没有登录
            return false;
        }
        HttpSession session = WebUtils.toHttp(request).getSession();
        Object sessionUsername = session.getAttribute(GlobalConstant.SESSION_AUTH_LOGIN_USERNAME);
        if (sessionUsername == null) {
            // 你自己的逻辑
            String userName = subject.getPrincipal().toString();
            SecurityUtils.getSubject().getSession().setAttribute(GlobalConstant.SESSION_AUTH_LOGIN_USERNAME,userName);
        }
        return true;
    }

    @Override
    protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {
        return true;
    }

    @Override
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
        return true;
    }
}
